/**
 * Copyright 2009-2019 the original author or authors.
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.ibatis.executor.resultset;

import org.apache.ibatis.annotations.AutomapConstructor;
import org.apache.ibatis.binding.MapperMethod.ParamMap;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.cursor.Cursor;
import org.apache.ibatis.cursor.defaults.DefaultCursor;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.ExecutorException;
import org.apache.ibatis.executor.loader.ResultLoader;
import org.apache.ibatis.executor.loader.ResultLoaderMap;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.result.DefaultResultContext;
import org.apache.ibatis.executor.result.DefaultResultHandler;
import org.apache.ibatis.executor.result.ResultMapException;
import org.apache.ibatis.mapping.*;
import org.apache.ibatis.reflection.MetaClass;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.ReflectorFactory;
import org.apache.ibatis.reflection.factory.ObjectFactory;
import org.apache.ibatis.session.*;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;
import org.apache.ibatis.type.TypeHandlerRegistry;

import java.lang.reflect.Constructor;
import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.*;

/**
 * 默认的ResultSet处理器
 *
 * @author Clinton Begin
 * @author Eduardo Macarron
 * @author Iwao AVE!
 * @author Kazuki Shimizu
 */
public class DefaultResultSetHandler implements ResultSetHandler {

    private static final Object DEFERRED = new Object();
    /**
     * Sql执行器
     */
    private final Executor executor;
    /**
     * Mybatis配置对象
     */
    private final Configuration configuration;
    /**
     * 方法映射声明语句
     */
    private final MappedStatement mappedStatement;
    /**
     * 分页处理器
     */
    private final RowBounds rowBounds;
    /**
     * 参数处理器
     */
    private final ParameterHandler parameterHandler;
    /**
     * 返回结果处理器
     */
    private final ResultHandler<?> resultHandler;
    /**
     * 对应的Sql数据
     */
    private final BoundSql boundSql;
    /**
     * 类型转换注册表
     */
    private final TypeHandlerRegistry typeHandlerRegistry;
    /**
     * 对象创建工厂
     */
    private final ObjectFactory objectFactory;
    /**
     * 反射工厂
     */
    private final ReflectorFactory reflectorFactory;

    /**
     * 嵌套的结果对象
     */
    // nested resultmaps
    private final Map<CacheKey, Object> nestedResultObjects = new HashMap<>();
    // 嵌套的返回结果对象  嵌套ResultMapId=> 值对象
    private final Map<String, Object> ancestorObjects = new HashMap<>();
    // 处理ResultSet返回结果集时，当前处理的上一行的数据的值
    private Object previousRowValue;

    /**
     * 涉及到多个返回结果集，即有多个子自段指向了不同的结果集
     */
    // multiple resultsets
    private final Map<String, ResultMapping> nextResultMaps = new HashMap<>();
    // 懒加载对象映射
    private final Map<CacheKey, List<PendingRelation>> pendingRelations = new HashMap<>();

    /**
     * 缓存自动映射的列
     */
    // Cached Automappings
    private final Map<String, List<UnMappedColumnAutoMapping>> autoMappingsCache = new HashMap<>();

    // 是否使用了构造方法的标志
    // temporary marking flag that indicate using constructor mapping (use field to reduce memory usage)
    private boolean useConstructorMappings;

    // 用于实现懒加载的实体定义
    private static class PendingRelation {
        /**
         *
         */
        public MetaObject metaObject;
        public ResultMapping propertyMapping;
    }

    /**
     * 未处理的自动映射的列
     */
    private static class UnMappedColumnAutoMapping {
        /**
         * 列名称
         */
        private final String column;
        /**
         * 属性名称
         */
        private final String property;
        /**
         * 类型转换处理器
         */
        private final TypeHandler<?> typeHandler;
        /**
         * 是否为基本类型
         */
        private final boolean primitive;

        public UnMappedColumnAutoMapping(String column, String property, TypeHandler<?> typeHandler, boolean primitive) {
            this.column = column;
            this.property = property;
            this.typeHandler = typeHandler;
            this.primitive = primitive;
        }
    }

    public DefaultResultSetHandler(Executor executor, MappedStatement mappedStatement, ParameterHandler parameterHandler, ResultHandler<?> resultHandler, BoundSql boundSql,
                                   RowBounds rowBounds) {
        this.executor = executor;
        this.configuration = mappedStatement.getConfiguration();
        this.mappedStatement = mappedStatement;
        this.rowBounds = rowBounds;
        this.parameterHandler = parameterHandler;
        this.boundSql = boundSql;
        this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
        this.objectFactory = configuration.getObjectFactory();
        this.reflectorFactory = configuration.getReflectorFactory();
        this.resultHandler = resultHandler;
    }

    //
    // HANDLE OUTPUT PARAMETER
    //

    @Override
    public void handleOutputParameters(CallableStatement cs) throws SQLException {
        // 获取入参对象
        final Object parameterObject = parameterHandler.getParameterObject();
        // 获取入参对象的元数据描述对象
        final MetaObject metaParam = configuration.newMetaObject(parameterObject);
        // 获取所有入参映射配置
        final List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        for (int i = 0; i < parameterMappings.size(); i++) {
            final ParameterMapping parameterMapping = parameterMappings.get(i);
            if (parameterMapping.getMode() == ParameterMode.OUT || parameterMapping.getMode() == ParameterMode.INOUT) {
                // 处理所有具有出参性质的参数
                if (ResultSet.class.equals(parameterMapping.getJavaType())) {
                    // 处理游标
                    handleRefCursorOutputParameter((ResultSet) cs.getObject(i + 1), parameterMapping, metaParam);
                } else {
                    // 获取类型转换处理器
                    final TypeHandler<?> typeHandler = parameterMapping.getTypeHandler();
                    // 处理普通参数
                    metaParam.setValue(parameterMapping.getProperty(), typeHandler.getResult(cs, i + 1));
                }
            }
        }
    }

    private void handleRefCursorOutputParameter(ResultSet rs, ParameterMapping parameterMapping, MetaObject metaParam) throws SQLException {
        if (rs == null) {
            return;
        }
        try {
            // 获取对应的返回映射配置的唯一标志
            final String resultMapId = parameterMapping.getResultMapId();
            final ResultMap resultMap = configuration.getResultMap(resultMapId);

            // 生成JDBC ResultSet对象的包装器
            final ResultSetWrapper rsw = new ResultSetWrapper(rs, configuration);
            if (this.resultHandler == null) {
                // 使用默认的返回结果处理器
                final DefaultResultHandler resultHandler = new DefaultResultHandler(objectFactory);
                // 处理每一行的值
                handleRowValues(rsw, resultMap, resultHandler, new RowBounds(), null);
                metaParam.setValue(parameterMapping.getProperty(), resultHandler.getResultList());
            } else {
                handleRowValues(rsw, resultMap, resultHandler, new RowBounds(), null);
            }
        } finally {
            // issue #228 (close resultsets)
            // 关闭ResultSet流
            closeResultSet(rs);
        }
    }

    //
    // HANDLE RESULT SETS
    //
    @Override
    public List<Object> handleResultSets(Statement stmt) throws SQLException {
        ErrorContext.instance().activity("handling results").object(mappedStatement.getId());

        // 定义多返回结果集
        final List<Object> multipleResults = new ArrayList<>();

        // 记录当前返回结果集的数量
        int resultSetCount = 0;
        // 包装ResultSet的第一个返回结果集
        ResultSetWrapper rsw = getFirstResultSet(stmt);
        // 获取声明映射语句对应的resultMap集合
        List<ResultMap> resultMaps = mappedStatement.getResultMaps();
        // 获取当前持有的resultMap的数量
        int resultMapCount = resultMaps.size();
        // 判断是否有有效的返回结果集
        validateResultMapsCount(rsw, resultMapCount);

        // 依次处理返回结果集
        while (rsw != null && resultMapCount > resultSetCount) {
            // 获取用户定义的返回结果集
            ResultMap resultMap = resultMaps.get(resultSetCount);
            // 处理记录
            handleResultSet(rsw, resultMap, multipleResults, null);

            // 继续处理下一行数据
            rsw = getNextResultSet(stmt);

            // 数据清理操作
            cleanUpAfterHandlingResultSet();
            // 更新计数器
            resultSetCount++;
        }
        // 多返回结果集
        String[] resultSets = mappedStatement.getResultSets();
        if (resultSets != null) {
            while (rsw != null && resultSetCount < resultSets.length) {
                // 获取下一个返回结果集配置
                ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);
                if (parentMapping != null) {
                    String nestedResultMapId = parentMapping.getNestedResultMapId();
                    ResultMap resultMap = configuration.getResultMap(nestedResultMapId);
                    handleResultSet(rsw, resultMap, null, parentMapping);
                }
                rsw = getNextResultSet(stmt);
                cleanUpAfterHandlingResultSet();
                resultSetCount++;
            }
        }
        // 将返回结果集处理成单个集合
        return collapseSingleResultList(multipleResults);
    }

    @Override
    public <E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException {
        ErrorContext.instance().activity("handling cursor results").object(mappedStatement.getId());

        ResultSetWrapper rsw = getFirstResultSet(stmt);

        List<ResultMap> resultMaps = mappedStatement.getResultMaps();

        int resultMapCount = resultMaps.size();
        validateResultMapsCount(rsw, resultMapCount);
        if (resultMapCount != 1) {
            throw new ExecutorException("Cursor results cannot be mapped to multiple resultMaps");
        }

        ResultMap resultMap = resultMaps.get(0);
        return new DefaultCursor<>(this, resultMap, rsw, rowBounds);
    }

    /**
     * 包装ResultSet
     *
     * @param stmt 声明语句
     * @return ResultSet包装器
     * @throws SQLException SQL异常
     */
    private ResultSetWrapper getFirstResultSet(Statement stmt) throws SQLException {
        // 获取返回结果集
        ResultSet rs = stmt.getResultSet();
        while (rs == null) {
            // move forward to get the first resultset in case the driver
            // doesn't return the resultset as the first result (HSQLDB 2.1)
            if (stmt.getMoreResults()) {
                // 如果有返回结果
                rs = stmt.getResultSet();
            } else {
                if (stmt.getUpdateCount() == -1) {
                    // no more results. Must be no resultset
                    break;
                }
            }
        }
        return rs != null ? new ResultSetWrapper(rs, configuration) : null;
    }

    private ResultSetWrapper getNextResultSet(Statement stmt) {
        // Making this method tolerant of bad JDBC drivers
        try {
            if (stmt.getConnection().getMetaData().supportsMultipleResultSets()) {
                // Crazy Standard JDBC way of determining if there are more results
                if (!(!stmt.getMoreResults() && stmt.getUpdateCount() == -1)) {
                    ResultSet rs = stmt.getResultSet();
                    if (rs == null) {
                        return getNextResultSet(stmt);
                    } else {
                        // 返回下一返回结果集
                        return new ResultSetWrapper(rs, configuration);
                    }
                }
            }
        } catch (Exception e) {
            // Intentionally ignored.
        }
        return null;
    }

    private void closeResultSet(ResultSet rs) {
        try {
            if (rs != null) {
                rs.close();
            }
        } catch (SQLException e) {
            // ignore
        }
    }

    private void cleanUpAfterHandlingResultSet() {
        nestedResultObjects.clear();
    }

    private void validateResultMapsCount(ResultSetWrapper rsw, int resultMapCount) {
        if (rsw != null && resultMapCount < 1) {
            throw new ExecutorException("A query was run and no Result Maps were found for the Mapped Statement '" + mappedStatement.getId()
                    + "'.  It's likely that neither a Result Type nor a Result Map was specified.");
        }
    }

    /**
     * 处理ResultSet
     *
     * @param rsw             ResultSet包装器
     * @param resultMap       ResultMap定义
     * @param multipleResults 返回结果
     * @param parentMapping   上级result定义
     * @throws SQLException SQL异常
     */
    private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException {
        try {
            if (parentMapping != null) {
                // parentMapping参数存在于具有嵌套性质的ResultMap中，简单来讲就是PO对象A中有一个属性B指向了另一个PO对象.
                // 具体表现为:在配置resultMapping的时候，使用了鉴别器，集合等配置。
                // 先处理上级
                handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping);
            } else {
                if (resultHandler == null) {
                    // 没有返回结果处理器,构建一个返回处理器
                    DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
                    // 处理每一行的值
                    handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);
                    // 添加多返回结果集
                    multipleResults.add(defaultResultHandler.getResultList());
                } else {
                    handleRowValues(rsw, resultMap, resultHandler, rowBounds, null);
                }
            }
        } finally {
            // 关闭流
            // issue #228 (close resultsets)
            closeResultSet(rsw.getResultSet());
        }
    }

    @SuppressWarnings("unchecked")
    private List<Object> collapseSingleResultList(List<Object> multipleResults) {
        return multipleResults.size() == 1 ? (List<Object>) multipleResults.get(0) : multipleResults;
    }

    //
    // HANDLE ROWS FOR SIMPLE RESULTMAP
    //

    /**
     * 处理简单的行
     *
     * @param rsw           ResultSet包装器
     * @param resultMap     resultMap
     * @param resultHandler 返回结果处理器
     * @param rowBounds     分页处理器
     * @param parentMapping 上级result定义
     * @throws SQLException SQL异常
     */
    public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {

        // 处理嵌套了的ResultMap
        if (resultMap.hasNestedResultMaps()) {
            // 当前resultMap拥有嵌套的ResultMap

            // 嵌套语句不允许使用RowBounds
            ensureNoRowBounds();
            // 检查返回结果处理器
            checkResultHandler();

            // 从嵌套结果集处理每一行的值
            handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);

        } else {
            //  处理简单的ResultMap
            // 从普通结果集处理每一行的值
            handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
        }
    }

    /**
     * 确保没有分页
     */
    private void ensureNoRowBounds() {
        if (configuration.isSafeRowBoundsEnabled()/*开启了内嵌分页功能*/
                && rowBounds != null /*含有分页对象*/
                && (rowBounds.getLimit() < RowBounds.NO_ROW_LIMIT /*有行数限制*/
                || rowBounds.getOffset() > RowBounds.NO_ROW_OFFSET /*有行数偏移*/
        )
        ) {
            throw new ExecutorException("Mapped Statements with nested result mappings cannot be safely constrained by RowBounds. "
                    + "Use safeRowBoundsEnabled=false setting to bypass this check.");
        }
    }

    /**
     * 校验返回结果处理器
     */
    protected void checkResultHandler() {
        if (resultHandler != null /*有返回结果处理器*/
                && configuration.isSafeResultHandlerEnabled() /*开启了嵌套查询应用返回结果处理器*/
                && !mappedStatement.isResultOrdered() /* TODO 嵌套的查询结果不是有序的*/
        ) {
            throw new ExecutorException("Mapped Statements with nested result mappings cannot be safely used with a custom ResultHandler. "
                    + "Use safeResultHandlerEnabled=false setting to bypass this check "
                    + "or ensure your statement returns ordered data and set resultOrdered=true on it.");
        }
    }

    private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
            throws SQLException {
        // 生成默认的返回结果处理上下文对象
        DefaultResultContext<Object> resultContext = new DefaultResultContext<>();

        // 获取JDBC ResultSet对象
        ResultSet resultSet = rsw.getResultSet();
        // 处理分页，移除前置无效记录
        skipRows(resultSet, rowBounds);

        // 一行一行的处理数据，直到不满足条件
        while (
                shouldProcessMoreRows(resultContext, rowBounds)/*是否需要继续读取下一行，主要作用是处理分页*/
                        && !resultSet.isClosed() /*返回结果没有被关闭*/
                        && resultSet.next()/*移动游标*/
        ) {
            // =======================================================================================================
            // 这一块的代码作用是获取到最终真正需要的ResultMap对象
            // 因为针对于鉴别器，此时方可确定其实际对应的ResultMap对象。
            // 处理鉴别器对应的返回结果映射配置，具体到鉴别器的case配置对应的resultMap，如果不是鉴别器，返回ResultMap本身。
            // =======================================================================================================
            ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(resultSet, resultMap, null);

            // 获取当前ResultMap对应的返回对象并赋值
            // 实际作用是将数据库数值映射为实际对象，完成这一步操作，不考虑懒加载属性的场景，设置操作已完成。
            Object rowValue = getRowValue(rsw, discriminatedResultMap, null);

            // 存储对象的操作有两种，一种是作为字段关联到所属的java对象，一种直接作为独立的对象被保存。
            storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
        }
    }

    private void storeObject(ResultHandler<?> resultHandler, DefaultResultContext<Object> resultContext, Object rowValue, ResultMapping parentMapping, ResultSet rs) throws SQLException {
        if (parentMapping != null) {
            // 如果是某个对象的属性，建立和所属对象的关系
            // 建立和上级映射器的关联关系
            linkToParents(rs, parentMapping, rowValue);
        } else {
            // 没有上一级
            callResultHandler(resultHandler, resultContext, rowValue);
        }
    }

    @SuppressWarnings("unchecked" /* because ResultHandler<?> is always ResultHandler<Object>*/)
    private void callResultHandler(ResultHandler<?> resultHandler, DefaultResultContext<Object> resultContext, Object rowValue) {
        // 刷新该行对应的值
        resultContext.nextResultObject(rowValue);
        // 处理
        ((ResultHandler<Object>) resultHandler).handleResult(resultContext);
    }

    /**
     * 判断是否需要读取更多的行
     *
     * @param context   返回结果上下文
     * @param rowBounds 分页定义类
     * @return 是否需要读取更多的行
     */
    private boolean shouldProcessMoreRows(ResultContext<?> context, RowBounds rowBounds) {
        return !context.isStopped()  /*返回结果没有停止使用*/
                && context.getResultCount() < rowBounds.getLimit()/*当前获取到的行数没有尚未满足分页条件*/;
    }

    /**
     * 跳过无效行，此处用来处理分页中的数据
     *
     * @param rs        返回结果集
     * @param rowBounds 分页配置
     * @throws SQLException Sql执行异常
     */
    private void skipRows(ResultSet rs, RowBounds rowBounds) throws SQLException {
        if (rs.getType() != ResultSet.TYPE_FORWARD_ONLY) {
            if (rowBounds.getOffset() != RowBounds.NO_ROW_OFFSET) {
                // 初始化返回结果的起始位置
                rs.absolute(rowBounds.getOffset());
            }
        } else {
            // 游标只可以前移
            for (int i = 0; i < rowBounds.getOffset(); i++) {
                if (!rs.next()) {
                    break;
                }
            }
        }
    }

    //
    // GET VALUE FROM ROW FOR SIMPLE RESULT MAP
    //

    /**
     * 根据JDBC ResultSet结果以及用户配置的ResultMap的配置，获取到运行期间该配置实际对应的值
     *
     * @param rsw          JDBC ResultSet
     * @param resultMap    用户配置的ResultMap对象
     * @param columnPrefix 统一列前缀
     */
    private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, String columnPrefix) throws SQLException {
        // 生成一个懒加载对象注册表，懒加载对象用来存储当前对象中的懒加载字段对应的对象

        // !! 懒加载字段集合，该集合中的数据均是尚未完全加载处理的属性，属性对应的实际值需要进一步查询数据库获取
        // ，这里维护的只是一个占位符而已。
        // 这些属性将会在后续的操作中被触发，参见代理对象JavassistProxyFactory
        final ResultLoaderMap lazyLoader = new ResultLoaderMap();

        // 生成一个返回结果对象，该对象只是完成了基本的实例化，并未完成其他属性的赋值操作
        Object rowValue = createResultObject(rsw, resultMap, lazyLoader, columnPrefix);

        if (rowValue != null &&
                !hasTypeHandlerForResultObject(rsw, resultMap.getType())
        ) {/*跳过有类型转换处理器的值*/
            // 获取返回对象的描述对象
            final MetaObject metaObject = configuration.newMetaObject(rowValue);
            boolean foundValues = this.useConstructorMappings;
            // isNested表示是否为嵌套语句
            // 是否自动映射列和属性值
            if (shouldApplyAutomaticMappings(resultMap, false)) {
                // 自动映射属性值
                foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues;
            }

            // 懒加载对象创建的位置，在牵扯到嵌套查询的时候，执行的设值操作，值其实是懒加载对象。
            foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues;

            foundValues = lazyLoader.size() > 0 || foundValues;
            // 是否允许返回null值
            rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;
        }
        // 返回对象
        return rowValue;
    }

    private boolean shouldApplyAutomaticMappings(ResultMap resultMap, boolean isNested) {
        if (resultMap.getAutoMapping() != null) {
            // 自动映射行为
            return resultMap.getAutoMapping();
        } else {
            if (isNested) {
                // 嵌套语句只有在FULL级别才开启自动映射行为
                return AutoMappingBehavior.FULL == configuration.getAutoMappingBehavior();
            } else {
                // 非嵌套语句只要不是NONE级别即开启自动映射行为
                return AutoMappingBehavior.NONE != configuration.getAutoMappingBehavior();
            }
        }
    }

    //
    // PROPERTY MAPPINGS
    //

    private boolean applyPropertyMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, ResultLoaderMap lazyLoader, String columnPrefix)
            throws SQLException {
        // 获取用户已配置的列名映射关系
        final List<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix);
        // 是否找到了值对象
        boolean foundValues = false;
        // 获取ResultSet下所有的普通属性节点
        final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();

        for (ResultMapping propertyMapping : propertyMappings) {
            // 获取完全的列名称
            String column = prependPrefix(propertyMapping.getColumn(), columnPrefix);
            if (propertyMapping.getNestedResultMapId() != null) {
                // 包含内嵌的返回结果集
                // the user added a column attribute to a nested result map, ignore it
                column = null;
            }
            if (propertyMapping.isCompositeResult() /*嵌套的resultMap定义*/
                    || (column != null && mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH)))/*已映射该字段*/
                    || propertyMapping.getResultSet() != null/*定义了返回结果集名称*/) {

                // 执行嵌套查询并将返回结果映射为指定类型的对象
                Object value = getPropertyMappingValue(rsw.getResultSet(), metaObject, propertyMapping, lazyLoader, columnPrefix);

                // issue #541 make property optional
                // 获取java属性名称
                final String property = propertyMapping.getProperty();
                if (property == null) {
                    continue;
                } else if (value == DEFERRED) {
                    // 懒加载
                    foundValues = true;
                    continue;
                }
                if (value != null) {
                    foundValues = true;
                }
                if (value != null/*嵌套查询有值*/
                        || (
                        configuration.isCallSettersOnNulls()/*当参数为null时，调用setter方法*/
                                && !metaObject.getSetterType(property).isPrimitive()/*入参对象不是基本类型*/
                )
                ) {
                    // 执行设值操作
                    // gcode issue #377, call setter on nulls (value is not 'found')
                    metaObject.setValue(property, value);
                }
            }
        }
        return foundValues;
    }

    private Object getPropertyMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderMap lazyLoader, String columnPrefix)
            throws SQLException {
        if (propertyMapping.getNestedQueryId() != null) {
            /*嵌套查询*/
            return getNestedQueryMappingValue(rs, metaResultObject, propertyMapping, lazyLoader, columnPrefix);
        } else if (propertyMapping.getResultSet() != null) {
            // 添加待填充的关系
            addPendingChildRelation(rs, metaResultObject, propertyMapping);   // TODO is that OK?
            return DEFERRED;
        } else {
            // 非嵌套查询，普通的一个字段
            final TypeHandler<?> typeHandler = propertyMapping.getTypeHandler();
            final String column = prependPrefix(propertyMapping.getColumn(), columnPrefix);
            // 返回实际值
            return typeHandler.getResult(rs, column);
        }
    }

    private List<UnMappedColumnAutoMapping> createAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {
        // 生成自动映射列名称的唯一标志，该标志仅仅用于缓存自动映射关系。
        final String mapKey = resultMap.getId() + ":" + columnPrefix;

        // 优先从缓存在读取自动映射关系
        List<UnMappedColumnAutoMapping> autoMapping = autoMappingsCache.get(mapKey);

        if (autoMapping == null) {
            // 未缓存自动映射关系
            // 初始化
            autoMapping = new ArrayList<>();

            // 获取所有未配置映射关系的列名称集合
            final List<String> unmappedColumnNames = rsw.getUnmappedColumnNames(resultMap, columnPrefix);
            // 依次处理
            for (String columnName : unmappedColumnNames) {
                // 获取列名称，propertyName表示对应的java字段名称
                String propertyName = columnName;
                if (columnPrefix != null && !columnPrefix.isEmpty()) {
                    // When columnPrefix is specified,
                    // ignore columns without the prefix.
                    if (columnName.toUpperCase(Locale.ENGLISH).startsWith(columnPrefix)) {
                        // 移除前缀
                        propertyName = columnName.substring(columnPrefix.length());
                    } else {
                        // 有统一前缀的时候，列名称不包含该前缀，将被忽略
                        continue;
                    }
                }
                // 根据配置决定是否依据下划线转驼峰的规则来查找属性名称
                final String property = metaObject.findProperty(propertyName, configuration.isMapUnderscoreToCamelCase());

                // 找到了对应的属性名称以及拥有对应的setter方法
                if (property != null && metaObject.hasSetter(property)) {
                    if (resultMap.getMappedProperties().contains(property)) {
                        continue;
                    }
                    // 获取对应的Setter方法的入参类型
                    final Class<?> propertyType = metaObject.getSetterType(property);
                    if (typeHandlerRegistry.hasTypeHandler(propertyType, rsw.getJdbcType(columnName))) {
                        // 有该入参的类型转换器
                        final TypeHandler<?> typeHandler = rsw.getTypeHandler(propertyType, columnName);
                        // 添加自动映射器
                        autoMapping.add(new UnMappedColumnAutoMapping(columnName, property, typeHandler, propertyType.isPrimitive()));
                    } else {
                        // 没有对应的类型转换处理器的时候，根据用户的配置，来决定具体是什么都不会做，记录警告日志，还是报错。
                        configuration.getAutoMappingUnknownColumnBehavior()
                                .doAction(mappedStatement, columnName, property, propertyType);
                    }
                } else {
                    // 没有找到属性或者没有对应的setter方法
                    configuration.getAutoMappingUnknownColumnBehavior()
                            .doAction(mappedStatement, columnName, (property != null) ? property : propertyName, null);
                }
            }
            // 添加到缓存中
            autoMappingsCache.put(mapKey, autoMapping);
        }
        return autoMapping;
    }

    private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {
        //  为那些没有配置数据库列和对象字段对应关系的列，生成对应关系。
        List<UnMappedColumnAutoMapping> autoMapping = createAutomaticMappings(rsw, resultMap, metaObject, columnPrefix);

        boolean foundValues = false;
        if (!autoMapping.isEmpty()) {
            // 处理这些自动映射的字段
            for (UnMappedColumnAutoMapping mapping : autoMapping) {
                // 获取对象属性对应的列值
                final Object value = mapping.typeHandler.getResult(rsw.getResultSet(), mapping.column);
                if (value != null) {
                    // 找到了值
                    foundValues = true;
                }
                if (value != null /*有值*/
                        || (configuration.isCallSettersOnNulls() && !mapping.primitive)/*允许为null值调用setter方法的同时，属性不是基本类型*/
                ) {
                    // gcode issue #377, call setter on nulls (value is not 'found')
                    // 设值 会触发懒加载
                    metaObject.setValue(mapping.property, value);
                }
            }
        }
        return foundValues;
    }

    // MULTIPLE RESULT SETS

    private void linkToParents(ResultSet rs, ResultMapping parentMapping, Object rowValue) throws SQLException {
        // 生成缓存key
        CacheKey parentKey = createKeyForMultipleResults(rs, parentMapping, parentMapping.getColumn(), parentMapping.getForeignColumn());
        // 获取现有的懒加载关系
        List<PendingRelation> parents = pendingRelations.get(parentKey);
        if (parents != null) {
            for (PendingRelation parent : parents) {
                if (parent != null && rowValue != null) {
                    // 关联懒加载对象和值
                    linkObjects(parent.metaObject, parent.propertyMapping, rowValue);
                }
            }
        }
    }

    private void addPendingChildRelation(ResultSet rs, MetaObject metaResultObject, ResultMapping parentMapping) throws SQLException {
        // 创建一个多返回结果集的缓存Key
        CacheKey cacheKey = createKeyForMultipleResults(rs, parentMapping, parentMapping.getColumn(), parentMapping.getColumn());
        PendingRelation deferLoad = new PendingRelation();
        // 返回结果对象
        deferLoad.metaObject = metaResultObject;
        // 对应的ResultMap子元素
        deferLoad.propertyMapping = parentMapping;
        // 获取等待懒加载的对象集合
        List<PendingRelation> relations = pendingRelations.computeIfAbsent(cacheKey, k -> new ArrayList<>());
        // issue #255
        // 添加一个懒加载对象
        relations.add(deferLoad);

        ResultMapping previous = nextResultMaps.get(parentMapping.getResultSet());
        if (previous == null) {
            // 未定义返回结果集
            nextResultMaps.put(parentMapping.getResultSet(), parentMapping);
        } else {
            if (!previous.equals(parentMapping)) {
                // 两个不同的属性映射到了同一个返回结果集上
                throw new ExecutorException("Two different properties are mapped to the same resultSet");
            }
        }
    }

    private CacheKey createKeyForMultipleResults(ResultSet rs, ResultMapping resultMapping, String names, String columns) throws SQLException {
        CacheKey cacheKey = new CacheKey();
        cacheKey.update(resultMapping);
        if (columns != null && names != null) {
            String[] columnsArray = columns.split(",");
            String[] namesArray = names.split(",");
            for (int i = 0; i < columnsArray.length; i++) {
                Object value = rs.getString(columnsArray[i]);
                if (value != null) {
                    cacheKey.update(namesArray[i]);
                    cacheKey.update(value);
                }
            }
        }
        return cacheKey;
    }

    //
    // INSTANTIATION & CONSTRUCTOR MAPPING
    //

    /**
     * 创建返回对象的实例
     *
     * @param rsw          返回结果集包装对象
     * @param resultMap    返回结果集映射
     * @param lazyLoader   懒加载对象集合
     * @param columnPrefix 统一数据库列名称前缀
     */
    private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {
        // 是否使用构造函数来进行属性配置
        this.useConstructorMappings = false; // reset previous mapping result

        // 构造参数相关参数
        final List<Class<?>> constructorArgTypes = new ArrayList<>(); // 构造参数类型集合(形参)
        final List<Object> constructorArgs = new ArrayList<>();  // 构造参数对象集合(实参)

        // 创建一个返回对象，此处只是完成了创建对象的工作，并没有完成所有所需字段赋值的操作
        Object resultObject = createResultObject(rsw, resultMap, constructorArgTypes, constructorArgs, columnPrefix);

        // 获取到了对象，且没有指定该对象的类型转换器
        if (
                resultObject != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())
        ) {
            // 获取ResultMap对应的所有<result>节点
            final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();
            for (ResultMapping propertyMapping : propertyMappings) {
                // issue gcode #109 && issue #149
                // !!! 懒加载对象就是在此处创建的
                // 如果<property>配置中引用了其他的查询语句，将会为该字段创建一个懒加载的代理对象。
                if (propertyMapping.getNestedQueryId() != null && propertyMapping.isLazy()) {
                    // 创建代理对象，实现懒加载,需要注意此处对象已经被代理了 (JavassistProxyFactory)
                    // 懒加载核心调用方
                    resultObject = configuration.getProxyFactory().createProxy(resultObject, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs);
                    break;
                }
            }
        }
        this.useConstructorMappings = resultObject != null && !constructorArgTypes.isEmpty(); // set current mapping result
        return resultObject;
    }

    /**
     * 创建返回对象
     *
     * @param rsw                 返回结果包装器
     * @param resultMap           返回结果映射表
     * @param constructorArgTypes 构造参数类型
     * @param constructorArgs     构造参数集合
     * @param columnPrefix        统一列名称前缀
     * @return 返回对象
     */
    private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, List<Class<?>> constructorArgTypes, List<Object> constructorArgs, String columnPrefix)
            throws SQLException {
        // 返回对象的类型，即返回映射结果集对应的Java类型
        final Class<?> resultType = resultMap.getType();
        // 通过反射工厂获取该返回类型的类描述元数据
        final MetaClass metaType = MetaClass.forClass(resultType, reflectorFactory);

        // 获取当前返回结果集下的构造参数配置
        final List<ResultMapping> constructorMappings = resultMap.getConstructorResultMappings();

        // 判断是否有该返回对象对应的类型转换处理器
        if (hasTypeHandlerForResultObject(rsw, resultType)) {
            // 在有该返回类型的类型转换处理器的前提下创建一个返回对象
            return createPrimitiveResultObject(rsw, resultMap, columnPrefix);
        } else if (!constructorMappings.isEmpty()) {
            // 拥有构造方法配置，使用构造方法实例化对象,这里还会进一步处理那些依赖于其他查询的构造参数
            return createParameterizedResultObject(rsw, resultType, constructorMappings, constructorArgTypes, constructorArgs, columnPrefix);

        } else if (resultType.isInterface() || metaType.hasDefaultConstructor()) {
            // 接口或者拥有默认的构造方法，尝试直接使用无参构造方法实例化
            return objectFactory.create(resultType);

        } else if (shouldApplyAutomaticMappings(resultMap, false)) {
            // 配置了自动映射
            return createByConstructorSignature(rsw, resultType, constructorArgTypes, constructorArgs, columnPrefix);

        }
        throw new ExecutorException("Do not know how to create an instance of " + resultType);
    }

    Object createParameterizedResultObject(ResultSetWrapper rsw, Class<?> resultType, List<ResultMapping> constructorMappings,
                                           List<Class<?>> constructorArgTypes, List<Object> constructorArgs, String columnPrefix) {
        // 是否找到了对应值的标识
        boolean foundValues = false;

        for (ResultMapping constructorMapping : constructorMappings) {
            // 处理每一个构造参数配置

            // 获取构造参数的java类型
            final Class<?> parameterType = constructorMapping.getJavaType();
            // 获取构造参数对应的数据库列名称
            final String column = constructorMapping.getColumn();

            // 数据库列将转化成的java对象
            final Object value;
            try {
                if (constructorMapping.getNestedQueryId() != null) {
                    // 拥有嵌套的查询语句，表示该构造参数对应的实际值需要进一步的查询才能使用
                    // 对于构造参数对应的嵌套查询语句，虽然会被处理成懒加载对象，但是该懒加载对象会立即被触发加载成实际值。
                    value = getNestedQueryConstructorValue(rsw.getResultSet(), constructorMapping, columnPrefix);
                } else if (constructorMapping.getNestedResultMapId() != null) {


                    // 如果该参数对应着另一个ResultMap配置，表示其也是一个复杂对象，需要进一步处理才能使用
                    final ResultMap resultMap = configuration.getResultMap(constructorMapping.getNestedResultMapId());
                    value = getRowValue(rsw, resultMap, constructorMapping.getColumnPrefix());
                } else {


                    // 该参数是一个简单配置的参数，将会直接使用类型转换处理器来完成映射并交付使用
                    final TypeHandler<?> typeHandler = constructorMapping.getTypeHandler();
                    value = typeHandler.getResult(rsw.getResultSet(), prependPrefix(column, columnPrefix));
                }
            } catch (ResultMapException | SQLException e) {
                throw new ExecutorException("Could not process result for mapping: " + constructorMapping, e);
            }
            // 保存构造类型和构造参数
            constructorArgTypes.add(parameterType);
            constructorArgs.add(value);
            foundValues = value != null || foundValues;
        }
        // 使用构造参数实例化对象或者跳过实例化操作
        return foundValues ? objectFactory.create(resultType, constructorArgTypes, constructorArgs) : null;
    }

    private Object createByConstructorSignature(ResultSetWrapper rsw, Class<?> resultType, List<Class<?>> constructorArgTypes, List<Object> constructorArgs,
                                                String columnPrefix) throws SQLException {
        // 获取所有的构造方法
        final Constructor<?>[] constructors = resultType.getDeclaredConstructors();
        // 获取指定的默认的构造方法，即标注了AutomapConstructor注解的方法
        final Constructor<?> defaultConstructor = findDefaultConstructor(constructors);
        if (defaultConstructor != null) {
            // 使用用户指定的构造方法实例化对象
            return createUsingConstructor(rsw, resultType, constructorArgTypes, constructorArgs, columnPrefix, defaultConstructor);
        } else {
            for (Constructor<?> constructor : constructors) {
                // 根据返回对象对应的构造参数以及数据库返回的JDBC类型来寻找合适的构造方法
                // 这里合适的构造方法表示: 参数数量和JDBC列数量一致，且所有的参数均能获取到对应的类型转换处理器
                if (allowedConstructorUsingTypeHandlers(constructor, rsw.getJdbcTypes())) {
                    // 实例化对象
                    return createUsingConstructor(rsw, resultType, constructorArgTypes, constructorArgs, columnPrefix, constructor);
                }
            }
        }
        throw new ExecutorException("No constructor found in " + resultType.getName() + " matching " + rsw.getClassNames());
    }

    private Object createUsingConstructor(ResultSetWrapper rsw, Class<?> resultType, List<Class<?>> constructorArgTypes, List<Object> constructorArgs, String columnPrefix, Constructor<?> constructor) throws SQLException {
        boolean foundValues = false;
        for (int i = 0; i < constructor.getParameterTypes().length; i++) {
            Class<?> parameterType = constructor.getParameterTypes()[i];
            String columnName = rsw.getColumnNames().get(i);
            TypeHandler<?> typeHandler = rsw.getTypeHandler(parameterType, columnName);
            Object value = typeHandler.getResult(rsw.getResultSet(), prependPrefix(columnName, columnPrefix));
            constructorArgTypes.add(parameterType);
            constructorArgs.add(value);
            foundValues = value != null || foundValues;
        }
        return foundValues ? objectFactory.create(resultType, constructorArgTypes, constructorArgs) : null;
    }

    private Constructor<?> findDefaultConstructor(final Constructor<?>[] constructors) {
        if (constructors.length == 1) return constructors[0];

        for (final Constructor<?> constructor : constructors) {
            // 获取标记了自动映射的构造函数注解(AutomapConstructor)的构造方法
            if (constructor.isAnnotationPresent(AutomapConstructor.class)) {
                return constructor;
            }
        }
        return null;
    }

    private boolean allowedConstructorUsingTypeHandlers(final Constructor<?> constructor, final List<JdbcType> jdbcTypes) {
        final Class<?>[] parameterTypes = constructor.getParameterTypes();
        if (parameterTypes.length != jdbcTypes.size()) return false;
        for (int i = 0; i < parameterTypes.length; i++) {
            if (!typeHandlerRegistry.hasTypeHandler(parameterTypes[i], jdbcTypes.get(i))) {
                return false;
            }
        }
        return true;
    }

    private Object createPrimitiveResultObject(ResultSetWrapper rsw, ResultMap resultMap, String columnPrefix) throws SQLException {
        // 获取返回的java类型
        final Class<?> resultType = resultMap.getType();
        final String columnName;

        // 根据用户是否配置了ResultMapping来生成对应的列名称，列名称用于类型转换处理器从数据库ResultSet读取值
        if (!resultMap.getResultMappings().isEmpty()) {
            // 获取当前返回结果映射配置中的所有子配置的第一个配置项
            final List<ResultMapping> resultMappingList = resultMap.getResultMappings();
            final ResultMapping mapping = resultMappingList.get(0);
            // 填充列名称前缀
            columnName = prependPrefix(mapping.getColumn(), columnPrefix);
        } else {
            // 获取列名称
            columnName = rsw.getColumnNames().get(0);
        }
        // 获取类型转换处理器
        final TypeHandler<?> typeHandler = rsw.getTypeHandler(resultType, columnName);
        // 使用类型转换处理器将数据库值转换成对应的JAVA对象
        return typeHandler.getResult(rsw.getResultSet(), columnName);
    }

    //
    // NESTED QUERY
    //

    private Object getNestedQueryConstructorValue(ResultSet rs, ResultMapping constructorMapping, String columnPrefix) throws SQLException {
        // 获取对应的嵌套的查询语句的全局唯一标志
        final String nestedQueryId = constructorMapping.getNestedQueryId();

        // 获取当前构造参数对应的内部查询语句定义
        final MappedStatement nestedQuery = configuration.getMappedStatement(nestedQueryId);

        // 获取内部查询对象的入参类型
        final Class<?> nestedQueryParameterType = nestedQuery.getParameterMap().getType();

        // 预处理内嵌的查询语句的参数
        final Object nestedQueryParameterObject = prepareParameterForNestedQuery(rs, constructorMapping, nestedQueryParameterType, columnPrefix);

        Object value = null;
        if (nestedQueryParameterObject != null) {
            // 获取一个用于执行的BoundSql对象
            final BoundSql nestedBoundSql = nestedQuery.getBoundSql(nestedQueryParameterObject);
            // 创建缓存Key
            final CacheKey key = executor.createCacheKey(nestedQuery, nestedQueryParameterObject, RowBounds.DEFAULT, nestedBoundSql);
            // 获取该查询语句对应的JAVA类型
            final Class<?> targetType = constructorMapping.getJavaType();
            // 注册懒加载对象
            final ResultLoader resultLoader = new ResultLoader(configuration, executor, nestedQuery, nestedQueryParameterObject, targetType, key, nestedBoundSql);
            // 直接加载该懒加载对象
            value = resultLoader.loadResult();
        }
        // 返回对应的实际值
        return value;
    }

    private Object getNestedQueryMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderMap lazyLoader, String columnPrefix)
            throws SQLException {
        // 获取嵌套的查询语句的唯一标志
        final String nestedQueryId = propertyMapping.getNestedQueryId();
        // 获取嵌套的查询语句对应的属性值
        final String property = propertyMapping.getProperty();
        // 获取嵌套的查询对应的查询语句声明对象
        final MappedStatement nestedQuery = configuration.getMappedStatement(nestedQueryId);
        // 获取嵌套的查询对应的入参对象配置，如果没有配置则为null
        final Class<?> nestedQueryParameterType = nestedQuery.getParameterMap().getType();
        // 解析出嵌套查询语句的入参对象及其对应的实际值
        final Object nestedQueryParameterObject = prepareParameterForNestedQuery(rs, propertyMapping, nestedQueryParameterType, columnPrefix);
        Object value = null;
        if (nestedQueryParameterObject != null) {
            // 准备执行嵌套查询
            // 获取嵌套查询语句对应的Sql对象
            final BoundSql nestedBoundSql = nestedQuery.getBoundSql(nestedQueryParameterObject);
            // 生成缓存Key
            final CacheKey key = executor.createCacheKey(nestedQuery, nestedQueryParameterObject, RowBounds.DEFAULT, nestedBoundSql);
            // 获取嵌套语句需要映射的目标对象类型
            final Class<?> targetType = propertyMapping.getJavaType();
            if (executor.isCached(nestedQuery, key)) {
                // 已缓存该对象
                executor.deferLoad(nestedQuery, metaResultObject, property, key, targetType);
                value = DEFERRED;
            } else {
                final ResultLoader resultLoader = new ResultLoader(configuration, executor, nestedQuery, nestedQueryParameterObject, targetType, key, nestedBoundSql);
                if (propertyMapping.isLazy()) {
                    // 懒加载
                    lazyLoader.addLoader(property, metaResultObject, resultLoader);
                    value = DEFERRED;
                } else {
                    // 设值
                    value = resultLoader.loadResult();
                }
            }
        }
        return value;
    }

    private Object prepareParameterForNestedQuery(ResultSet rs, ResultMapping resultMapping, Class<?> parameterType, String columnPrefix) throws SQLException {
        if (resultMapping.isCompositeResult()) {

            // 处理复合查询 比如[column="{id=vip}"]
            return prepareCompositeKeyParameter(rs, resultMapping, parameterType, columnPrefix);
        } else {
            // 处理简单查询
            return prepareSimpleKeyParameter(rs, resultMapping, parameterType, columnPrefix);
        }
    }

    private Object prepareSimpleKeyParameter(ResultSet rs, ResultMapping resultMapping, Class<?> parameterType, String columnPrefix) throws SQLException {
        final TypeHandler<?> typeHandler;
        if (typeHandlerRegistry.hasTypeHandler(parameterType)) {
            typeHandler = typeHandlerRegistry.getTypeHandler(parameterType);
        } else {
            typeHandler = typeHandlerRegistry.getUnknownTypeHandler();
        }
        return typeHandler.getResult(rs, prependPrefix(resultMapping.getColumn(), columnPrefix));
    }

    /**
     * 预处理符合参数
     *
     * @param rs            JDBC 返回结果集
     * @param resultMapping 对应的ResultMapping配置
     * @param parameterType 对应的入参类型
     * @param columnPrefix  统一的列前缀
     */
    private Object prepareCompositeKeyParameter(ResultSet rs, ResultMapping resultMapping, Class<?> parameterType, String columnPrefix) throws SQLException {
        // 实例化需要的参数，并且获取其描述对象
        // 具体的对象实例或者HashMap
        final Object parameterObject = instantiateParameterObject(parameterType);
        // 创建入参对象的描述对象
        final MetaObject metaObject = configuration.newMetaObject(parameterObject);


        boolean foundValues = false;
        // 处理返回结果集中包含的符合配置
        // 获取所有以column={a=c,b=d}的方式定义出来的ResultMapping对象
        for (ResultMapping innerResultMapping : resultMapping.getComposites()) {
            // 获取符合对象对应的属性名称，并在入参对象中查找到对象的setter方法
            final Class<?> propType = metaObject.getSetterType(innerResultMapping.getProperty());
            // 获取符合对象对应属性的类型转换处理器
            final TypeHandler<?> typeHandler = typeHandlerRegistry.getTypeHandler(propType);
            // 获取返回结果集中，对应字段的值，该值将会用于执行嵌套查询
            final Object propValue = typeHandler.getResult(rs, prependPrefix(innerResultMapping.getColumn(), columnPrefix));
            // issue #353 & #560 do not execute nested query if key is null
            if (propValue != null) {
                // 往入参对象中设值
                metaObject.setValue(innerResultMapping.getProperty(), propValue);
                foundValues = true;
            }
        }
        return foundValues ? parameterObject : null;
    }

    private Object instantiateParameterObject(Class<?> parameterType) {
        if (parameterType == null) {
            return new HashMap<>();
        } else if (ParamMap.class.equals(parameterType)) {
            return new HashMap<>(); // issue #649
        } else {
            // 指定了入参对象类型，调用对象创建工厂创建一个实例
            return objectFactory.create(parameterType);
        }
    }

    //
    // DISCRIMINATOR
    //

    /**
     * 解析鉴别器在实际过程中对应的ResultMap对象
     *
     * @param rs           返回结果集
     * @param resultMap    鉴别器所属的ResultMap
     * @param columnPrefix 列名前缀
     */
    public ResultMap resolveDiscriminatedResultMap(ResultSet rs, ResultMap resultMap, String columnPrefix) throws SQLException {
        // 已经处理过的鉴别器集合，该参数可以用来排除掉循环引用鉴别器的场景，所以该参数很重要
        Set<String> pastDiscriminators = new HashSet<>();

        // 获取当前返回结果集中定义的鉴别器
        Discriminator discriminator = resultMap.getDiscriminator();

        // 如果有鉴别器则处理鉴别器，无鉴别器则直接返回原始的ResultMap对象

        while (discriminator != null) {
            // 获取鉴别器对象中对应的值，该值将会用来确定具体使用的鉴别器子配置:
            // 即:<case value="该值">...</case>
            final Object value = getDiscriminatorValue(rs, discriminator, columnPrefix);
            // 根据当前列对应的值，获取到鉴别器对应的ResultMap对象
            final String discriminatedMapId = discriminator.getMapIdFor(String.valueOf(value));

            if (configuration.hasResultMap(discriminatedMapId)) {
                // !! 获取到鉴别器实际对应的ResultMap对象,需要注意的是，这里刷新了ResultMap对象实例.
                // 因此如果鉴别器中继续嵌套鉴别器，最终返回的是最后一个不重复的鉴别器。

                resultMap = configuration.getResultMap(discriminatedMapId);

                // 缓存上一个鉴别器对象的引用
                Discriminator lastDiscriminator = discriminator;

                // 继续处理鉴别器
                discriminator = resultMap.getDiscriminator();

                // 获取嵌套的resultMap对应的鉴别器
                if (discriminator == lastDiscriminator || !pastDiscriminators.add(discriminatedMapId)) {
                    // 避免出现死循环
                    break;
                }
            } else {
                break;
            }
        }
        // 返回鉴别器对应的返回结果映射配置
        return resultMap;
    }

    /**
     * 获取鉴别器对应的数据库列实际的值
     *
     * @param rs            JDBC返回结果集
     * @param discriminator 鉴别器对象
     * @param columnPrefix  统一列前缀
     */
    private Object getDiscriminatorValue(ResultSet rs, Discriminator discriminator, String columnPrefix) throws SQLException {
        // 获取鉴别器本身配置,主要是它对应的数据库列名称等配置
        final ResultMapping resultMapping = discriminator.getResultMapping();

        // 获取类型转换处理器
        final TypeHandler<?> typeHandler = resultMapping.getTypeHandler();

        // 获取该鉴别器对应的值
        return typeHandler.getResult(rs, prependPrefix(resultMapping.getColumn(), columnPrefix));
    }

    /**
     * 执行添加列前缀的操作
     *
     * @param columnName 列名称
     * @param prefix     前缀
     */
    private String prependPrefix(String columnName, String prefix) {
        if (columnName == null || columnName.length() == 0 || prefix == null || prefix.length() == 0) {
            return columnName;
        }
        return prefix + columnName;
    }

    //
    // HANDLE NESTED RESULT MAPS
    //

    /**
     * 处理嵌套的返回结果集
     *
     * @param rsw           ResultSet包装器
     * @param resultMap     resultMap
     * @param resultHandler 返回结果处理器
     * @param rowBounds     分页类
     * @param parentMapping 上级result定义
     * @throws SQLException SQL异常
     */
    private void handleRowValuesForNestedResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
        // 构建一个上下文对象
        final DefaultResultContext<Object> resultContext = new DefaultResultContext<>();
        ResultSet resultSet = rsw.getResultSet();
        // 跳过无效行,主要是跳过分页配置的前面的行数
        skipRows(resultSet, rowBounds);
        // !!! 上一行的对象
        Object rowValue = previousRowValue;

        // 判断是否需要处理更多的行数，主要作用是处理分页
        while (shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) {

            // 解析当前ResultMap对象是否指向了一个鉴别器,如果指向了一个鉴别器,则解析该鉴别器获取其对应的ResultMap对象。
            final ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(resultSet, resultMap, null);

            // 创建缓存key
            final CacheKey rowKey = createRowKey(discriminatedResultMap, rsw, null);

            // 获取是否已经缓存过该鉴别器
            // 缓存的嵌套结果对象
            Object partialObject = nestedResultObjects.get(rowKey);

            // issue #577 && #542
            if (mappedStatement.isResultOrdered()) {
                // 需要对返回结果进行排序
                if (partialObject == null && rowValue != null) {
                    // 如果相同主键的数据是顺序出现的,那么相应的数据是能够从临时缓存中获取的
                    // 这一步的目的是,清理之前的所有缓存,节省空间.
                    // 未缓存该嵌套解雇对象,同时当前数据不是第一行
                    // 清除所有缓存的对象数据
                    nestedResultObjects.clear();
                    // 缓存并应用该对象(处理的是上一行的数据)
                    storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
                }
                // 继续加载下一行的数据,有缓存用缓存,无缓存则新建
                rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, null, partialObject);
            } else {
                // 无需排序
                rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, null, partialObject);
                if (partialObject == null) {
                    // 在未命中缓存的前提下,才会保存数据关系
                    // 当前对象未被缓存
                    // 缓存并应用该对象
                    storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
                }
            }
        }

        if (rowValue != null && mappedStatement.isResultOrdered() && shouldProcessMoreRows(resultContext, rowBounds)) {
            storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
            previousRowValue = null;
        } else if (rowValue != null) {
            previousRowValue = rowValue;
        }
    }

    //
    // GET VALUE FROM ROW FOR NESTED RESULT MAP
    //

    /**
     * 处理嵌套的ResultMap
     * <p>
     * 和applyNestedResultMappings递归调用
     */
    private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, CacheKey combinedKey, String columnPrefix, Object partialObject) throws SQLException {
        // 获取当前需要处理的resultMap的唯一标志
        final String resultMapId = resultMap.getId();

        Object rowValue = partialObject;
        if (rowValue != null) {
            // 获取所属对象元数据
            final MetaObject metaObject = configuration.newMetaObject(rowValue);

            // 记录当前需要处理的ResultMap对象以及其所属的对象的关系
            putAncestor(rowValue, resultMapId);

            // 将引用关系转换为实际值
            applyNestedResultMappings(rsw, resultMap, metaObject, columnPrefix, combinedKey, false);

            // 移除需要处理的ResultMap对象以及其所属的对象的关系
            ancestorObjects.remove(resultMapId);

        } else {
            // 生成懒加载对象
            final ResultLoaderMap lazyLoader = new ResultLoaderMap();
            // 该方法会根据配置来决定是否生成懒加载对象
            rowValue = createResultObject(rsw, resultMap, lazyLoader, columnPrefix);

            // 生成了属性对象，同时该属性没有对应的类型转换处理器
            if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
                // 生成对象描述元数据对象
                final MetaObject metaObject = configuration.newMetaObject(rowValue);

                boolean foundValues = this.useConstructorMappings;

                //  applyAutomaticMappings加applyPropertyMappings包含了所有字段

                // 自动映射
                if (shouldApplyAutomaticMappings(resultMap, true)) {
                    foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues;
                }

                // 用户配置的属性映射
                foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues;

                // 缓存当前属性已被处理
                putAncestor(rowValue, resultMapId);
                foundValues = applyNestedResultMappings(rsw, resultMap, metaObject, columnPrefix, combinedKey, true) || foundValues;
                // 移除缓存
                ancestorObjects.remove(resultMapId);

                foundValues = lazyLoader.size() > 0 || foundValues;
                rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;
            }
            if (combinedKey != CacheKey.NULL_CACHE_KEY) {
                // 入缓存
                nestedResultObjects.put(combinedKey, rowValue);
            }
        }
        return rowValue;
    }

    private void putAncestor(Object resultObject, String resultMapId) {

        ancestorObjects.put(resultMapId, resultObject);
    }

    //
    // NESTED RESULT MAP (JOIN MAPPING)
    //

    /**
     * @param rsw          JDBC ResultSet包装器
     * @param resultMap    返回结果集
     * @param metaObject   返回对象的元数据描述对象
     * @param parentPrefix 返回结果集持有者的前缀
     * @param parentRowKey 返回结果集持有者的缓存key
     * @param newObject    是否是新对象
     */
    private boolean applyNestedResultMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String parentPrefix, CacheKey parentRowKey, boolean newObject) {
        boolean foundValues = false;

        // 处理ResultMap对象定义的所有ResultMapping
        for (ResultMapping resultMapping : resultMap.getPropertyResultMappings()) {
            // 获取嵌套的ResultMap标志，并不是所有的ResultMapping都有NestedResultMapId，或者说，只有个别的才会有NestedResultMapId。
            // 因此接下来的IF代码块并不是每次都执行的。
            final String nestedResultMapId = resultMapping.getNestedResultMapId();

            if (nestedResultMapId != null /*有NestedResultMapId定义*/
                    && resultMapping.getResultSet() == null/*没有指定其对应的结果集*/
            ) {
                // 有嵌套的ResultMap，同时没有指定返回结果集名称
                try {
                    // 获取列名前缀
                    final String columnPrefix = getColumnPrefix(parentPrefix, resultMapping);
                    // 获取嵌套的ResultMap配置
                    final ResultMap nestedResultMap = getNestedResultMap(rsw.getResultSet(), nestedResultMapId, columnPrefix);

                    // column=column+columnPrefix
                    if (resultMapping.getColumnPrefix() == null) {
                        // 没有指定列名前缀
                        // try to fill circular reference only when columnPrefix
                        // is not specified for the nested result map (issue #215)
                        // 获取当前ResultMap所属的对象

                        // ancestorObjects里对象的生命周期是被applyNestedResultMappings方法调用方维护的，
                        // 在现有的代码中，其生命周期均为在调用applyNestedResultMappings方法之前添加key值为nestedResultMapId的引用，
                        // 在调用方法后移除Key值为nestedResultMapId的引用。
                        // 所以ancestorObjects中维护的属性必然是A.B.C...N..的类型，其中A,B,C均表示为JAVA对象.
                        // 因此如果在ancestorObjects中根据nestedResultMapId获取到了对象，只能表示该对象出现了循环引用，即A.B.A这种场景。
                        //     : A对象中持有的B对象又持有了A对象的引用。
                        // 所以这一步很重要，可以排除掉无限递归处理的场景
                        Object ancestorObject = ancestorObjects.get(nestedResultMapId);
                        if (ancestorObject != null) {
                            // 该参数控制是否需要创建resultMapping对应JAVA属性的实例
                            if (newObject) {
                                // 关联
                                linkObjects(metaObject, resultMapping, ancestorObject); // issue #385
                            }
                            continue;
                        }
                    }
                    // 生成嵌套的ResultMap的缓存Key
                    final CacheKey rowKey = createRowKey(nestedResultMap, rsw, columnPrefix);
                    // 合并缓存Key
                    final CacheKey combinedKey = combineKeys(rowKey, parentRowKey);
                    // 从缓存中读取对应的查询结果
                    Object rowValue = nestedResultObjects.get(combinedKey);
                    // 判断当前属性是否已经被处理过
                    boolean knownValue = rowValue != null;
                    // 如果当前ResultMapping对应的是一个Collection对象，该属性会被初始化且赋值给metaObject对象
                    // 否则，什么事都不会做。
                    instantiateCollectionPropertyIfAppropriate(resultMapping, metaObject); // mandatory

                    // 判断指定的ResultMapping对象中定义的非空字段是否至少有一个可以被赋值。
                    if (anyNotNullColumnHasValue(resultMapping, columnPrefix, rsw)) {
                        // 获取当前ResultMapping对应的值，此处就和getRowValue形成了递归调用的关系
                        // 这样一个递归解决了多层ResultMap嵌套的问题。
                        rowValue = getRowValue(rsw, nestedResultMap, combinedKey, columnPrefix, rowValue);

                        // 获取到值，且未被处理过
                        if (rowValue != null && !knownValue) {

                            // 关联
                            linkObjects(metaObject, resultMapping, rowValue);
                            foundValues = true;
                        }
                    }
                } catch (SQLException e) {
                    throw new ExecutorException("Error getting nested result map values for '" + resultMapping.getProperty() + "'.  Cause: " + e, e);
                }
            }
        }
        return foundValues;
    }

    /**
     * 完成对列名前缀的追加操作
     *
     * @param parentPrefix  父级列前缀
     * @param resultMapping 当前返回字段配置
     */
    private String getColumnPrefix(String parentPrefix, ResultMapping resultMapping) {
        final StringBuilder columnPrefixBuilder = new StringBuilder();
        if (parentPrefix != null) {
            columnPrefixBuilder.append(parentPrefix);
        }
        if (resultMapping.getColumnPrefix() != null) {
            columnPrefixBuilder.append(resultMapping.getColumnPrefix());
        }
        return columnPrefixBuilder.length() == 0 ? null : columnPrefixBuilder.toString().toUpperCase(Locale.ENGLISH);
    }

    /**
     * 判断指定的ResultMapping对象中定义的非空字段是否至少有一个可以被赋值。
     *
     * @param resultMapping ResultMapping对象
     * @param columnPrefix  列名前缀
     * @param rsw           ResultSet包装器
     */
    private boolean anyNotNullColumnHasValue(ResultMapping resultMapping, String columnPrefix, ResultSetWrapper rsw) throws SQLException {
        // 获取非空字段集合
        Set<String> notNullColumns = resultMapping.getNotNullColumns();

        // 有非空字段
        if (notNullColumns != null && !notNullColumns.isEmpty()) {
            ResultSet rs = rsw.getResultSet();
            for (String column : notNullColumns) {
                rs.getObject(prependPrefix(column, columnPrefix));
                if (!rs.wasNull()) {
                    return true;
                }
            }
            return false;
        } else if (columnPrefix != null) {
            // 未定义非空字段
            for (String columnName : rsw.getColumnNames()) {
                if (columnName.toUpperCase().startsWith(columnPrefix.toUpperCase())) {
                    // 是否有任意一个可以匹配的数据列
                    return true;
                }
            }
            return false;
        }
        return true;
    }

    private ResultMap getNestedResultMap(ResultSet rs, String nestedResultMapId, String columnPrefix) throws SQLException {
        ResultMap nestedResultMap = configuration.getResultMap(nestedResultMapId);
        // 执行一次解析鉴别器的处理
        return resolveDiscriminatedResultMap(rs, nestedResultMap, columnPrefix);
    }

    //
    // UNIQUE RESULT KEY
    //

    private CacheKey createRowKey(ResultMap resultMap, ResultSetWrapper rsw, String columnPrefix) throws SQLException {
        final CacheKey cacheKey = new CacheKey();
        cacheKey.update(resultMap.getId());
        List<ResultMapping> resultMappings = getResultMappingsForRowKey(resultMap);
        if (resultMappings.isEmpty()) {
            if (Map.class.isAssignableFrom(resultMap.getType())) {
                createRowKeyForMap(rsw, cacheKey);
            } else {
                createRowKeyForUnmappedProperties(resultMap, rsw, cacheKey, columnPrefix);
            }
        } else {
            createRowKeyForMappedProperties(resultMap, rsw, cacheKey, resultMappings, columnPrefix);
        }
        if (cacheKey.getUpdateCount() < 2) {
            return CacheKey.NULL_CACHE_KEY;
        }
        return cacheKey;
    }

    private CacheKey combineKeys(CacheKey rowKey, CacheKey parentRowKey) {
        if (rowKey.getUpdateCount() > 1 && parentRowKey.getUpdateCount() > 1) {
            CacheKey combinedKey;
            try {
                combinedKey = rowKey.clone();
            } catch (CloneNotSupportedException e) {
                throw new ExecutorException("Error cloning cache key.  Cause: " + e, e);
            }
            combinedKey.update(parentRowKey);
            return combinedKey;
        }
        return CacheKey.NULL_CACHE_KEY;
    }

    private List<ResultMapping> getResultMappingsForRowKey(ResultMap resultMap) {
        List<ResultMapping> resultMappings = resultMap.getIdResultMappings();
        if (resultMappings.isEmpty()) {
            resultMappings = resultMap.getPropertyResultMappings();
        }
        return resultMappings;
    }

    private void createRowKeyForMappedProperties(ResultMap resultMap, ResultSetWrapper rsw, CacheKey cacheKey, List<ResultMapping> resultMappings, String columnPrefix) throws SQLException {
        for (ResultMapping resultMapping : resultMappings) {
            if (resultMapping.getNestedResultMapId() != null && resultMapping.getResultSet() == null) {
                // Issue #392
                final ResultMap nestedResultMap = configuration.getResultMap(resultMapping.getNestedResultMapId());
                createRowKeyForMappedProperties(nestedResultMap, rsw, cacheKey, nestedResultMap.getConstructorResultMappings(),
                        prependPrefix(resultMapping.getColumnPrefix(), columnPrefix));
            } else if (resultMapping.getNestedQueryId() == null) {
                final String column = prependPrefix(resultMapping.getColumn(), columnPrefix);
                final TypeHandler<?> th = resultMapping.getTypeHandler();
                List<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix);
                // Issue #114
                if (column != null && mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH))) {
                    // 加载数据
                    final Object value = th.getResult(rsw.getResultSet(), column);
                    if (value != null || configuration.isReturnInstanceForEmptyRow()) {
                        cacheKey.update(column);
                        cacheKey.update(value);
                    }
                }
            }
        }
    }

    private void createRowKeyForUnmappedProperties(ResultMap resultMap, ResultSetWrapper rsw, CacheKey cacheKey, String columnPrefix) throws SQLException {
        final MetaClass metaType = MetaClass.forClass(resultMap.getType(), reflectorFactory);
        List<String> unmappedColumnNames = rsw.getUnmappedColumnNames(resultMap, columnPrefix);
        for (String column : unmappedColumnNames) {
            String property = column;
            if (columnPrefix != null && !columnPrefix.isEmpty()) {
                // When columnPrefix is specified, ignore columns without the prefix.
                if (column.toUpperCase(Locale.ENGLISH).startsWith(columnPrefix)) {
                    property = column.substring(columnPrefix.length());
                } else {
                    continue;
                }
            }
            if (metaType.findProperty(property, configuration.isMapUnderscoreToCamelCase()) != null) {
                String value = rsw.getResultSet().getString(column);
                if (value != null) {
                    cacheKey.update(column);
                    cacheKey.update(value);
                }
            }
        }
    }

    private void createRowKeyForMap(ResultSetWrapper rsw, CacheKey cacheKey) throws SQLException {
        List<String> columnNames = rsw.getColumnNames();
        for (String columnName : columnNames) {
            final String value = rsw.getResultSet().getString(columnName);
            if (value != null) {
                cacheKey.update(columnName);
                cacheKey.update(value);
            }
        }
    }

    /**
     * 关联指定的ResultMapping属性同java对象的从属关系
     *
     * @param metaObject    ResultMapping对象所属的Java对象的元数据
     * @param resultMapping resultMapping
     * @param rowValue      ResultMapping对象所属的Java对象的元数据
     */
    private void linkObjects(MetaObject metaObject, ResultMapping resultMapping, Object rowValue) {

        // 尝试将对象处理成集合对象，如果指定的对象不是集合对象则返回null.
        final Object collectionProperty = instantiateCollectionPropertyIfAppropriate(resultMapping, metaObject);

        if (collectionProperty != null) {
            // 可以转成集合对象
            // 集合属性
            final MetaObject targetMetaObject = configuration.newMetaObject(collectionProperty);
            // 集合类型往集合中追加值
            targetMetaObject.add(rowValue);
        } else {
            // 简单属性直接赋值
            metaObject.setValue(resultMapping.getProperty(), rowValue);
        }
    }

    /**
     * 尝试实例化集合类型的属性，注意，此处只会处理Collection类型的属性
     *
     * @param resultMapping resultMapping
     * @param metaObject    所属java对象
     */
    private Object instantiateCollectionPropertyIfAppropriate(ResultMapping resultMapping, MetaObject metaObject) {
        // 获取JAVA属性名称
        final String propertyName = resultMapping.getProperty();
        // 获取JAVA属性值
        Object propertyValue = metaObject.getValue(propertyName);

        if (propertyValue == null) {
            // 没有获取到属性值，获取到该属性的类型
            Class<?> type = resultMapping.getJavaType();
            if (type == null) {
                // 根据setter方法获取
                type = metaObject.getSetterType(propertyName);
            }
            // 如果该属性是一个集合类型，实例化该属性并赋值到所属到的对象中
            try {
                if (objectFactory.isCollection(type)) {
                    // 实体对象是集合
                    propertyValue = objectFactory.create(type);
                    // 设值
                    metaObject.setValue(propertyName, propertyValue);
                    // 返回值
                    return propertyValue;
                }
            } catch (Exception e) {
                throw new ExecutorException("Error instantiating collection property for result '" + resultMapping.getProperty() + "'.  Cause: " + e, e);
            }
        } else if (objectFactory.isCollection(propertyValue.getClass())) {
            // 直接返回
            return propertyValue;
        }
        return null;
    }

    /**
     * 是否指定对象的返回结果处理器
     *
     * @param rsw        返回结果包装器
     * @param resultType 返回类型
     * @return 是否有所需的返回结果处理器
     */
    private boolean hasTypeHandlerForResultObject(ResultSetWrapper rsw, Class<?> resultType) {
        if (rsw.getColumnNames().size() == 1) {
            // 数据库对应的数据只有一列，即表示只查询一个字段
            // 判断类型转换器注册表中是否有该JDBC类型和该JAVA类型的转换器
            return typeHandlerRegistry.hasTypeHandler(resultType, rsw.getJdbcType(rsw.getColumnNames().get(0)));
        }
        // 如果查询多个数据库字段，则判断是否持有对应JAVA类型的类型转换处理器
        return typeHandlerRegistry.hasTypeHandler(resultType);
    }

}
